<?php


/**
 *
 * Class constructing and optimizing an XML answer of a client HTTP request
 * It's known by Model classes & Controller.
 * It contains the DOM document also for generating the responseNode.
 *
 * It constructs an XML Response by adding different nodes to the root element
 * So, nodes passed to add method must be just under the root element.
 *
 * This class specified also the XSL sheet to apply to the final XML tree before sending the response to the client.
 *
 * @copyright inovia
 * @package oolime_core
 *
 */
class Response {

	/**
	 * This is the XML Document which is built and send
	 * @var DOMDocument
	 */
	public $doc;

	/**
	 * This is the root element of the DOMDocument
	 * @var DOMElement
	 */
	public $root;

	/**
	 * This is the root element of the debug info
	 * @var DOMElement
	 */
	public $DebugElement;

	/**
	 * This is the root element of the inforamtion node
	 * @var DOMElement
	 */
	public $InfoElement;

	/**
	 * This is the XPath parser of the DOMDocument
	 * @var DOMXpath
	 */
	public $responseXPathParser;



	public  $XmlXslt;
	private $idC;
	public  $session;
	public  $user;

	/**
	 * Constructor
	 */
	public function __construct(){
		global $session;
		global $user;
		$this->user = &$user;
		$this->session = &$session;
		//Constructs the DomDocument
		$this->doc = new DOMDocumentPerso('1.0', 'ISO-8859-1');
		//Constructs a root element
		$this->root = new DOMElement('site');
		//Appends the root element to the DomDocument
		$this->doc->appendChild($this->root);

		$this->DebugElement = new DOMElement('debug');
		$this->InfoElement  = new DOMElement('infos');
		//Appends the debug element to the DomDocument
		$this->root->appendChild($this->DebugElement);
		//Appends the info element to the DomDocument
		$this->root->appendChild($this->InfoElement);


	}

	/**
	 * Initializes the session with the user data
	 */
	public function initSession(){
		if(isset($this->user) && isset($this->user->field->group)) {
			// Constructs the attribute level of session
			$this->root->setAttribute("group",$this->user->field->group);
			// Constructs the attribute login of session
			$this->root->setAttribute("user",$this->user->field->user);
			// Constructs the attribute lang of session
		}
		if(isset($_SESSION["lang"])) $this->root->setAttribute("lang",$_SESSION["lang"]);

	}



	/**
	 * Function adding a node just under the root element.
	 *    It a synomnim to root->appendChild($node), but it is here for clarity in the code.
	 *    We can  more accurately detect the nodes not append to the response.
	 *
	 * @param DOMnode node, the node to add to the response
	 */
	public function add($node){
		//appends the DomElement to the root
		$this->root->appendChild($node);
	}

	/**
	 *  Adds debug info to the node debug, dont use it with accent chara...*
	 *  @param string the debug message
	 */
	public function addDebug($string){
		$keyNode    = $this->doc->createElement("info");
		$keyMessage = $this->doc->createTextNode($string);
		$keyNode->appendChild($keyMessage);
		$this->DebugElement->appendChild($keyNode);
	}


	/**
	 * Adds info to the node info
	 * @param DOMNode the info node
	 */
	public function addInfo($node){
		$this->InfoElement->appendChild($node);
	}




	/**
	 * Adds an error node to the response Node
	 *
	 * @param string $errorString
	 * @param int $idED
	 */
	public function addError($errorString,$key = false){
		// creation of the node "error"
		$errorNode = $this->doc->createElement("error");
		if($key) {
			// creation of the node "key", depending on the node "error", containing the key representing the reason of the error
			$keyNode    = $this->doc->createElement("key");
			$keyMessage = $this->doc->createTextNode($key);
			$keyNode->appendChild($keyMessage);
			$errorNode->appendChild($keyNode);
		}

		// creation of the node "text", depending on the node "error", containing the error description
		$textNode     = $this->doc->createElement("text");
		$textMessage  = $this->doc->createTextNode($errorString);
		$textNode->appendChild($textMessage);
		$errorNode->appendChild($textNode);

		// add the error to the response node
		$this->add($errorNode);
	}

	/**
	 * Function sending the corresponding answer to the built response
	 * @param bool optimized, true if the string must be optimized
	 */
	public function finalize($optimized){

		//set the $optimized type
		settype($optimized,"bool");

		//prints the XML File compressed
		if($optimized) {
			//ob_start("ob_gzhandler");
			echo $this->doc->saveXML();
			//ob_end_flush();
		}else {
			echo $this->doc->saveXML();
		}
	}

	public function getIdC(){
		return $this->idC;
	}

	public function setIdC($id){
		$this->idC = $id;
	}

	/**
	 * Function testing the existence of a given node
	 * @param string nodepath, XPath expression of the node
	 * @return the number of found nodes
	 */
	public function nodeCount($nodepath){
		if (trim($nodepath)!=''){
			$query = $this->responseXPathParser->query($nodepath);
		}
		return $query->length;
	}

	/**
	 * Looks for a given node in the Response Tree
	 * @param string nodepath, XPath expression of the node
	 * @return if the query returns a single node, returns the DOMElement, else returns false
	 */
	public function getNode($nodepath){
		if (trim($nodepath)!=''){
			$query = $this->responseXPathParser->query($nodepath);
		}
		if ($query->length==1) return $query->item(0); // Sucess
		return false; // Failure
	}



	/**
	 * Method to set the XSLTsheet which will be used
	 * The param is the path of the sheet
	 *
	 *@param string $XSLname
	 */
	public function setXSLT($XSLTname) {
		include_once("core/xmlxslt.php");

		global $configDebugXSLT;
		$this->XmlXslt = new XmlXslt();
		$this->XmlXslt->setXML($this->doc);
		//if($configDebugXSLT) print_r("Opening the file \"".$XSLTname."\"<br />");
		$this->XmlXslt->loadXSL($XSLTname);
	}


	/**
	 * Method called by the eventDispatcher
	 *
	 */
	public function processXSLT() {
		return $this->XmlXslt->getResult();
	}

	public function rss($url){
		$arbre = null;
		if((!$this->url_exists($url))){
			return false;
		}
		if (($fp  = fopen($url, "r")) === FALSE){
			return false;
		}
		while (!feof ($fp)) $arbre .= fgets($fp, 4096);
		
		$arbre = utf8_encode($arbre);
		$arbre = str_replace("xmlns=", 'xmlns:atom=', $arbre);
		
		fclose ($fp);

		$sxe     = simplexml_load_string($arbre);
		
		$dom_sxe = dom_import_simplexml($sxe);
			
		$dom_sxe = $this->doc->importNode($dom_sxe,true);
		$this->add($dom_sxe);
		
	}

	function getTextFromNode($Node, $Text = "") {
		if ($Node->tagName == null)
		return $Text.$Node->textContent;

		$Node = $Node->firstChild;
		if ($Node != null)
		$Text = "[{$Node->tagName}]\n".$this->getTextFromNode($Node, $Text)."\n[/{$Node->tagName}]\n";

		while($Node->nextSibling != null) {
			$Text = "[{$Node->tagName}]\n".$this->getTextFromNode($Node->nextSibling, $Text)."\n[/{$Node->tagName}]\n";
			$Node = $Node->nextSibling;
		}
		return $Text;
	}

	public function url_exists($url){
			

		$AgetHeaders = @get_headers($url);
		if (preg_match("|200|", $AgetHeaders[0])) {
			return true;
		} else {
			return false;
		}
		/**
		 $file_headers = @get_headers($url);
		 if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
		 return false;
		 }
		 else {
		 return true;
		 }**/
	}


	/**
	 * Maps attrbiutes (specified in an association array) of an object into an XML node
	 * @param object the object to map
	 * @param string the name of the node returned
	 * @param array association table attributename => elementName
	 * @return DOMNode an XML node cntaining attributes specified in the association table
	 */
	public function mapObjectXML ($obj, $nodeName, $tab) {
		$ParentNode = $this->doc->createElement($nodeName);
		while(list($key,$val) = each($tab)) {
			try{
				$SonNode  = $this->doc->createElement($val);
				
				
				$valueSon = $this->doc->createTextNode($obj->{$key});
				
				
				$SonNode->appendChild($valueSon);
				
				$ParentNode->appendChild($SonNode);
				
				$SonNode  = null;
				$valueSon = null;
			}
			catch(Exception $e){
				$this->addError3("probleme au mapping de key".$key." value ".$val);
			}
		}
		return $ParentNode;
	}


}



/**
 * Upgrade of the DOMDocument type to manage correctly the latin chars
 * @package oolime_core
 *
 */
class DOMDocumentPerso extends DOMDocument {
	private function modifyText($string) {
		return stripslashes($string);
	}
	public function createTextNode($string) {
		return DOMDocument::createTextNode($this->modifyText($string));
		
	}

}


?>
